//
//  BaseNetManager.m
//  BaseProject
//
//  Created by 孟瑞瑞 on 15/10/21.
//  Copyright © 2018年 CSDN. All rights reserved.
//

#import "BaseNetManager.h"
#import <AVFoundation/AVAsset.h>
#import <AVFoundation/AVAssetExportSession.h>
#import <AVFoundation/AVMediaFormat.h>

/*! 系统相册 */
#import <Photos/Photos.h>
#import <AFNetworking/AFNetworking.h>
#import <AFNetworking/AFNetworkActivityIndicatorManager.h>
#import "BaseNetManagerCache.h"
#import <YunCeng/YunCeng.h>
#import "CAUtils.h"
#import "CNAccountInfoTool.h"
#import <AlicloudHttpDNS/AlicloudHttpDNS.h>
#import <CNBaseTool/CNCategoryHeader.h>
#import <CNBaseTool/UUIDTool.h>
#import "CNChangeHostManager.h"
#import <CNBaseNetWorkTool/CNBaseNetWorkTool-Swift.h>
#import "CNBaseNetworkConst.h"


static NSMutableArray *tasks;

static NSString * const CLOUDAPI_LF = @"\n";
static NSString * const GATEWAY_APPKEY = @"203792824";
static NSString * const GATEWAY_APPSECRET = @"l04vqptqf3fnelcd0p4bexluztfml54i";

//static void *isNeedCacheKey = @"isNeedCacheKey";

//#ifndef __OPTIMIZE__
//#define NSLog(...) NSLog(__VA_ARGS__)
//#else
//#define NSLog(...){}
//#endif

@interface BaseNetManager ()

@property(nonatomic, strong) AFHTTPSessionManager *sessionManager;

@property (nonatomic, assign) NSInteger randomNum;

@end

@implementation BaseNetManager

+ (instancetype)sharedBANetManager
{
    /*! 为单例对象创建的静态实例，置为nil，因为对象的唯一性，必须是static类型 */
    static id sharedBANetManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedBANetManager = [[super allocWithZone:NULL] init];
    });
    return sharedBANetManager;
}

+ (void)initialize
{
    [self setupBANetManager];
}

+ (void)setupBANetManager
{
    BANetManagerShare.sessionManager = [AFHTTPSessionManager manager];
    
    BANetManagerShare.requestSerializer = BAHttpRequestSerializerJSON;
    BANetManagerShare.responseSerializer = BAHttpResponseSerializerJSON;
    
    /*! 打开状态栏的等待菊花 */
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
    /*! 设置返回数据类型为 json, 分别设置请求以及相应的序列化器 */
    /*!
     根据服务器的设定不同还可以设置：
     json：[AFJSONResponseSerializer serializer](常用)
     http：[AFHTTPResponseSerializer serializer]
     */
    //    AFJSONResponseSerializer *response = [AFJSONResponseSerializer serializer];
    //    /*! 这里是去掉了键值对里空对象的键值 */
    ////    response.removesKeysWithNullValues = YES;
    //    BANetManagerShare.sessionManager.responseSerializer = response;
    
    /* 设置请求服务器数类型式为 json */
    /*!
     根据服务器的设定不同还可以设置：
     json：[AFJSONRequestSerializer serializer](常用)
     http：[AFHTTPRequestSerializer serializer]
     */
    //    AFJSONRequestSerializer *request = [AFJSONRequestSerializer serializer];
    //    BANetManagerShare.sessionManager.requestSerializer = request;
    /*! 设置apikey ------类似于自己应用中的tokken---此处仅仅作为测试使用*/
    //        [manager.requestSerializer setValue:apikey forHTTPHeaderField:@"apikey"];
    
    /*! 复杂的参数类型 需要使用json传值-设置请求内容的类型*/
    //        [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    
    /*! 设置响应数据的基本类型 */
    BANetManagerShare.sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/css", @"text/xml", @"text/plain", @"application/javascript", @"image/*", @"application/x-www-form-urlencoded", @"multipart/form-data", nil];
    
    
    [BANetManagerShare.sessionManager.requestSerializer setValue:@"zh-cn" forHTTPHeaderField:@"X-Accept-Language"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:@"ios" forHTTPHeaderField:@"platform"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:[CNAccountInfoTool appVersion] forHTTPHeaderField:@"version"];
    
    [BANetManagerShare.sessionManager.requestSerializer setValue:[CNAccountInfoTool uuidString] forHTTPHeaderField:@"X-Device-ID"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:@"CSDN-APP" forHTTPHeaderField:@"X-App-ID"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:@"iOS" forHTTPHeaderField:@"X-OS"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:[CNAccountInfoTool getCSDNAccessToken] forHTTPHeaderField:@"X-Access-Token"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"X-Ca-Signed-Content-Type"];
    
    char deviceToken[384] = {0};
    int re =[YunCeng GetSession:deviceToken :384];
    NSString * astring = [NSString stringWithUTF8String:deviceToken];
    
    [BANetManagerShare.sessionManager.requestSerializer setValue:astring forHTTPHeaderField:@"DeviceToken"];
    
    
    //BANetManagerShare.sessionManager.requestSerializer.HTTPMethodsEncodingParametersInURI = [NSSet setWithArray:@[@"GET", @"HEAD"]];
    //BANetManagerShare.sessionManager.requestSerializer.HTTPMethodsEncodingParametersInURI = [NSSet setWithArray:@[@"GET", @"POST", @"HEAD"]];
    
    [BANetManagerShare.sessionManager.requestSerializer setStringEncoding:NSUTF8StringEncoding];
    
    /*! 设置请求超时时间，默认：30秒 */
    BANetManagerShare.timeoutInterval = 40;
    //最大请求并发任务数
    BANetManagerShare.sessionManager.operationQueue.maxConcurrentOperationCount = 4;
    BANetManagerShare.sessionManager.session.configuration.HTTPMaximumConnectionsPerHost = 50;
    // 配置自建证书的Https请求
    [self ba_setupSecurityPolicy];
}

/**
 配置自建证书的Https请求，只需要将CA证书文件放入根目录就行
 */
+ (void)ba_setupSecurityPolicy
{
    //    NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
    NSSet <NSData *> *cerSet = [AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]];
    
    if (cerSet.count == 0)
    {
        /*!
         采用默认的defaultPolicy就可以了. AFN默认的securityPolicy就是它, 不必另写代码. AFSecurityPolicy类中会调用苹果security.framework的机制去自行验证本次请求服务端放回的证书是否是经过正规签名.
         */
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
        securityPolicy.allowInvalidCertificates = YES;
        securityPolicy.validatesDomainName = NO;
        BANetManagerShare.sessionManager.securityPolicy = securityPolicy;
    }
    else
    {
        /*! 自定义的CA证书配置如下： */
        /*! 自定义security policy, 先前确保你的自定义CA证书已放入工程Bundle */
        /*!
         https://api.github.com网址的证书实际上是正规CADigiCert签发的, 这里把Charles的CA根证书导入系统并设为信任后, 把Charles设为该网址的SSL Proxy (相当于"中间人"), 这样通过代理访问服务器返回将是由Charles伪CA签发的证书.
         */
        // 使用证书验证模式
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:cerSet];
        // 如果需要验证自建证书(无效证书)，需要设置为YES
        securityPolicy.allowInvalidCertificates = YES;
        // 是否需要验证域名，默认为YES
        //    securityPolicy.pinnedCertificates = [[NSSet alloc] initWithObjects:cerData, nil];
        
        BANetManagerShare.sessionManager.securityPolicy = securityPolicy;
        
        
        /*! 如果服务端使用的是正规CA签发的证书, 那么以下几行就可去掉: */
        //            NSSet <NSData *> *cerSet = [AFSecurityPolicy certificatesInBundle:[NSBundle mainBundle]];
        //            AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:cerSet];
        //            policy.allowInvalidCertificates = YES;
        //            BANetManagerShare.sessionManager.securityPolicy = policy;
    }
}

#pragma mark - 网络请求的类方法 --- get / post / put / delete
/*!
 *  网络请求的实例方法
 *
 *  @param type         get / post / put / delete
 *  @param isNeedCache  是否需要缓存，只有 get / post 请求有缓存配置
 *  @param urlString    请求的地址
 *  @param parameters    请求的参数
 *  @param successBlock 请求成功的回调
 *  @param failureBlock 请求失败的回调
 *  @param progressBlock 进度
 */
+ (BAURLSessionTask *)ba_requestWithType:(BAHttpRequestType)type
                             isNeedCache:(BOOL)isNeedCache
                               urlString:(NSString *)urlString
                              parameters:(id)parameters
                            successBlock:(BAResponseSuccessBlock)successBlock
                            failureBlock:(BAResponseFailBlock)failureBlock
                           progressBlock:(BADownloadProgressBlock)progressBlock
{
    
    @synchronized ([self superclass]) {
        if (urlString == nil)
        {
            return nil;
        }
        
        BAWeak;
        /*! 检查地址中是否有中文 */
        NSString *URLString = [NSURL URLWithString:urlString] ? urlString : [self strUTF8Encoding:urlString];
        
        NSString *requestType;
        switch (type) {
            case 0:
                requestType = @"GET";
                break;
            case 1:
                requestType = @"POST";
                break;
            case 2:
                requestType = @"PUT";
                break;
            case 3:
                requestType = @"DELETE";
                break;
                
            default:
                break;
        }
        
        
        [BANetManagerShare.sessionManager.requestSerializer setValue:[CNAccountInfoTool csdnIsAudit]?@"1":@"0" forHTTPHeaderField:@"isCsdnAudit"];
        [BANetManagerShare.sessionManager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",(([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditToken]:CN_GWTToken)] forHTTPHeaderField:@"Authorization"];
        if ((([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin]) && [CNAccountInfoTool auditToken] != nil) || [[NSUserDefaults standardUserDefaults]objectForKey:kCSDNToken]!= nil)
        {
            //配置Token
            [BANetManagerShare.sessionManager.requestSerializer setValue:(([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditToken]:CN_GWTToken) forHTTPHeaderField:@"JWT-TOKEN"];
        }else
        {
            [BANetManagerShare.sessionManager.requestSerializer setValue:nil forHTTPHeaderField:@"JWT-TOKEN"];
        }
        
        [BANetManagerShare.sessionManager.requestSerializer setValue:(([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditUserToken]:[CNAccountInfoTool userToken]) forHTTPHeaderField:@"UserToken"];
        //签名
        NSInteger randomNum = [CSDNTool getRandomNumber:10000 to:100000];
        NSString *currentTimeStamp = [CSDNTool currentTimeStampStr];
        DDLogDebug(@"%@",[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret]);
        NSString *sign = [[[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret] sha1String] uppercaseString];
        [BANetManagerShare.sessionManager.requestSerializer setValue:sign forHTTPHeaderField:@"X-Sign"];
        [BANetManagerShare.sessionManager.requestSerializer setValue:[NSString stringWithFormat:@"%ld",randomNum] forHTTPHeaderField:@"X-RandomNum"];
        [BANetManagerShare.sessionManager.requestSerializer setValue:currentTimeStamp forHTTPHeaderField:@"X-TimeStamp"];
        [BANetManagerShare.sessionManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        
        //阿里云API网关接入参数
        [self signAliyunApiGatewayWithMethod:requestType AndPath:[NSURL URLWithString:URLString].path AndParams:parameters];
        
        
        AFHTTPSessionManager *scc = BANetManagerShare.sessionManager;
        AFHTTPResponseSerializer *scc2 = scc.responseSerializer;
        AFHTTPRequestSerializer *scc3 = scc.requestSerializer;
        NSTimeInterval timeoutInterval = BANetManagerShare.timeoutInterval;
        
        NSString *isCache = isNeedCache ? @"开启":@"关闭";
        CGFloat allCacheSize = [BaseNetManagerCache ba_getAllHttpCacheSize];
        
        if (BANetManagerShare.isOpenLog)
        {
            DDLogDebug(@"\n******************** 请求参数 ***************************");
            DDLogDebug(@"\n请求头: %@\n超时时间设置：%.1f 秒【默认：30秒】\nAFHTTPResponseSerializer：%@【默认：AFJSONResponseSerializer】\nAFHTTPRequestSerializer：%@【默认：AFJSONRequestSerializer】\n请求方式: %@\n请求URL: %@\n请求param: %@\n是否启用缓存：%@【默认：开启】\n目前总缓存大小：%.6fM\n", BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders, timeoutInterval, scc2, scc3, requestType, URLString, parameters, isCache, allCacheSize);
            DDLogDebug(@"\n********************************************************");
        }
        
        if ([CNBaseNetworkConst closeHTTPDNS]) {
            [self ba_setValue:nil forHTTPHeaderKey:@"host"];
        }else{
            // 初始化httpdns实例
            HttpDnsService *httpdns = [HttpDnsService sharedInstance];
            NSURL *aliyunUrl = [NSURL URLWithString:URLString];
            NSString *ip = [httpdns getIpByHostAsync:aliyunUrl.host];
            //    DDLogDebug(@"+++++++阿里云IP:%@",ip);
            [self ba_setValue:aliyunUrl.host forHTTPHeaderKey:@"host"];
            if (ip) {
                // 通过HTTPDNS获取IP成功，进行URL替换和HOST头设置
                //        DDLogDebug(@"+++++++阿里云Get IP(%@) for host(%@) from HTTPDNS Successfully!", ip, aliyunUrl.host);
                NSRange hostFirstRange = [URLString rangeOfString:aliyunUrl.host];
                if (NSNotFound != hostFirstRange.location) {
                    NSString *newUrl = [URLString stringByReplacingCharactersInRange:hostFirstRange withString:ip];
                    //            DDLogDebug(@"New URL: %@", newUrl);
                    //            DDLogDebug(@"+++++++阿里云New URL:%@",newUrl);
                    URLString = newUrl;
                }
            }
        }
        
        
        //    DDLogDebug(@"+++++++阿里云最终URL:%@",URLString);
        
        
        BAURLSessionTask *sessionTask = nil;
        
        // 读取缓存
        id responseCacheData = [BaseNetManagerCache ba_httpCacheWithUrlString:urlString parameters:parameters];
        
        if (isNeedCache && responseCacheData != nil && [self ba_isHaveNetwork] != YES)// 自己加了一个没有网络时读取缓存数据
        {
            if (successBlock)
            {
                successBlock(responseCacheData);
            }
            if (BANetManagerShare.isOpenLog)
            {
                DDLogDebug(@"取用缓存数据结果： *** %@", responseCacheData);
            }
            
            @synchronized([weakSelf tasks]){
                [[weakSelf tasks] removeObject:sessionTask];
            }
            return nil;
        }
        
        if (BANetManagerShare.isSetQueryStringSerialization)
        {
            [BANetManagerShare.sessionManager.requestSerializer setQueryStringSerializationWithBlock:^NSString * _Nonnull(NSURLRequest * _Nonnull request, id  _Nonnull parameters, NSError * _Nullable __autoreleasing * _Nullable error) {
                
                return parameters;
                
            }];
        }
        
        if (type == BAHttpRequestTypeGet)
        {
            sessionTask = [BANetManagerShare.sessionManager GET:URLString parameters:parameters headers:nil  progress:^(NSProgress * _Nonnull downloadProgress) {
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                if (successBlock)
                {
                    successBlock(responseObject);
                }
                // 对数据进行异步缓存
                [BaseNetManagerCache ba_setHttpCache:responseObject urlString:urlString parameters:parameters];
                @synchronized([weakSelf tasks]){
                    [[weakSelf tasks] removeObject:sessionTask];
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                if (failureBlock)
                {
                    failureBlock(error);
                }
                @synchronized([weakSelf tasks]){
                    [[weakSelf tasks] removeObject:sessionTask];
                }
                NSMutableDictionary *userInfo = [[NSMutableDictionary alloc]init];
                userInfo[NSLocalizedDescriptionKey] = error.localizedDescription;
                userInfo[CNServiceRequestParam] =  [parameters yy_modelToJSONString];
                userInfo[CNServiceRequestUrl] = URLString;
                NSError *customError = [NSError errorWithDomain:@"CNServiceErrorDomain" code:error.code userInfo:userInfo];
//                [[CNLogManager shareManager] uploadLogWithError:customError];
            }];
        }
        else if (type == BAHttpRequestTypePost)
        {
            sessionTask = [BANetManagerShare.sessionManager POST:URLString parameters:parameters headers:nil progress:^(NSProgress * _Nonnull uploadProgress) {
                if (BANetManagerShare.isOpenLog)
                {
                    DDLogDebug(@"上传进度--%lld, 总进度---%lld",uploadProgress.completedUnitCount,uploadProgress.totalUnitCount);
                }
                
                /*! 回到主线程刷新UI */
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (progressBlock)
                    {
                        progressBlock(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
                    }
                });
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                if (BANetManagerShare.isOpenLog)
                {
                    DDLogDebug(@"post 请求数据结果： *** %@", responseObject);
                }
                
                if (successBlock)
                {
                    successBlock(responseObject);
                }
                
                // 对数据进行异步缓存
                [BaseNetManagerCache ba_setHttpCache:responseObject urlString:urlString parameters:parameters];
                @synchronized([weakSelf tasks]){
                    [[weakSelf tasks] removeObject:sessionTask];
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                if (BANetManagerShare.isOpenLog)
                {
                    DDLogError(@"错误信息：%@",error);
                }
                
                if (failureBlock)
                {
                    failureBlock(error);
                }
                @synchronized([weakSelf tasks]){
                    [[weakSelf tasks] removeObject:sessionTask];
                }
                NSMutableDictionary *userInfo = [[NSMutableDictionary alloc]init];
                userInfo[NSLocalizedDescriptionKey] = error.localizedDescription;
                userInfo[CNServiceRequestParam] =  [parameters yy_modelToJSONString];
                userInfo[CNServiceRequestUrl] = URLString;
                NSError *customError = [NSError errorWithDomain:@"CNServiceErrorDomain" code:error.code userInfo:userInfo];
                [[CNLogManager shareManager] uploadLogWithError:customError];
            }];
        }
        else if (type == BAHttpRequestTypePut)
        {
            sessionTask = [BANetManagerShare.sessionManager PUT:URLString parameters:parameters headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                if (successBlock)
                {
                    successBlock(responseObject);
                }
                
                @synchronized([weakSelf tasks]){
                    [[weakSelf tasks] removeObject:sessionTask];
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                if (failureBlock)
                {
                    failureBlock(error);
                }
                @synchronized([weakSelf tasks]){
                    [[weakSelf tasks] removeObject:sessionTask];
                }
                
            }];
        }
        else if (type == BAHttpRequestTypeDelete)
        {
            sessionTask = [BANetManagerShare.sessionManager DELETE:URLString parameters:parameters headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                if (successBlock)
                {
                    successBlock(responseObject);
                }
                
                @synchronized([weakSelf tasks]){
                    [[weakSelf tasks] removeObject:sessionTask];
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                if (failureBlock)
                {
                    failureBlock(error);
                }
                @synchronized([weakSelf tasks]){
                    [[weakSelf tasks] removeObject:sessionTask];
                }
            }];
        }
        
        if (sessionTask)
        {
            @synchronized([weakSelf tasks]){
                [[weakSelf tasks] addObject:sessionTask];
            }
        }
        
        return sessionTask;
    }
}

#pragma mark - 网络请求的类方法 + Entity --- get / post / put / delete

/**
 网络请求的实例方法 get
 
 @param entity 请求信息载体
 @param successBlock 请求成功的回调
 @param failureBlock 请求失败的回调
 @param progressBlock 进度回调
 @return BAURLSessionTask
 */
+ (BAURLSessionTask *)ba_request_GETWithEntity:(BADataEntity *)entity
                                  successBlock:(BAResponseSuccessBlock)successBlock
                                  failureBlock:(BAResponseFailBlock)failureBlock
                                 progressBlock:(BADownloadProgressBlock)progressBlock
{
    if (!entity || ![entity isKindOfClass:[BADataEntity class]]) {
        return nil;
    }
    return [self ba_requestWithType:BAHttpRequestTypeGet isNeedCache:entity.isNeedCache urlString:entity.urlString
                         parameters:entity.parameters successBlock:successBlock failureBlock:failureBlock progressBlock:progressBlock];
}

/**
 网络请求的实例方法 post
 
 @param entity 请求信息载体
 @param successBlock 请求成功的回调
 @param failureBlock 请求失败的回调
 @param progressBlock 进度
 @return BAURLSessionTask
 */
+ (BAURLSessionTask *)ba_request_POSTWithEntity:(BADataEntity *)entity
                                   successBlock:(BAResponseSuccessBlock)successBlock
                                   failureBlock:(BAResponseFailBlock)failureBlock
                                  progressBlock:(BADownloadProgressBlock)progressBlock
{
    if (!entity || ![entity isKindOfClass:[BADataEntity class]]) {
        return nil;
    }
    return [self ba_requestWithType:BAHttpRequestTypePost isNeedCache:entity.isNeedCache urlString:entity.urlString parameters:entity.parameters successBlock:successBlock failureBlock:failureBlock progressBlock:progressBlock];
}

/**
 网络请求的实例方法 put
 
 @param entity 请求信息载体
 @param successBlock 请求成功的回调
 @param failureBlock 请求失败的回调
 @param progressBlock 进度
 @return BAURLSessionTask
 */
+ (BAURLSessionTask *)ba_request_PUTWithEntity:(BADataEntity *)entity
                                  successBlock:(BAResponseSuccessBlock)successBlock
                                  failureBlock:(BAResponseFailBlock)failureBlock
                                 progressBlock:(BADownloadProgressBlock)progressBlock
{
    if (!entity || ![entity isKindOfClass:[BADataEntity class]]) {
        return nil;
    }
    return [self ba_requestWithType:BAHttpRequestTypePut isNeedCache:NO urlString:entity.urlString parameters:entity.parameters successBlock:successBlock failureBlock:failureBlock progressBlock:progressBlock];
}

/**
 网络请求的实例方法 delete
 
 @param entity 请求信息载体
 @param successBlock 请求成功的回调
 @param failureBlock 请求失败的回调
 @param progressBlock 进度
 @return BAURLSessionTask
 */
+ (BAURLSessionTask *)ba_request_DELETEWithEntity:(BADataEntity *)entity
                                     successBlock:(BAResponseSuccessBlock)successBlock
                                     failureBlock:(BAResponseFailBlock)failureBlock
                                    progressBlock:(BADownloadProgressBlock)progressBlock
{
    if (!entity || ![entity isKindOfClass:[BADataEntity class]]) {
        return nil;
    }
    return [self ba_requestWithType:BAHttpRequestTypeDelete isNeedCache:NO urlString:entity.urlString parameters:entity.parameters successBlock:successBlock failureBlock:failureBlock progressBlock:progressBlock];
}

/**
 上传图片(多图)
 
 @param entity 请求信息载体
 @param successBlock 上传成功的回调
 @param failureBlock 上传失败的回调
 @param progressBlock 上传进度
 @return BAURLSessionTask
 */
+ (BAURLSessionTask *)ba_uploadImageWithEntity:(BADataEntity *)entity
                                  successBlock:(BAResponseSuccessBlock)successBlock
                                   failurBlock:(BAResponseFailBlock)failureBlock
                                 progressBlock:(BAUploadProgressBlock)progressBlock
{
    [BANetManagerShare.sessionManager.requestSerializer setValue:[CNAccountInfoTool csdnIsAudit]?@"1":@"0" forHTTPHeaderField:@"isCsdnAudit"];
    //签名
    NSInteger randomNum = [CSDNTool getRandomNumber:10000 to:100000];
    NSString *currentTimeStamp = [CSDNTool currentTimeStampStr];
    //    DDLogDebug(@"%@",[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret]);
    NSString *sign = [[[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret] sha1String] uppercaseString];
    [BANetManagerShare.sessionManager.requestSerializer setValue:sign forHTTPHeaderField:@"X-Sign"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:[NSString stringWithFormat:@"%ld",randomNum] forHTTPHeaderField:@"X-RandomNum"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:currentTimeStamp forHTTPHeaderField:@"X-TimeStamp"];
    if (!entity || entity.urlString == nil || ![entity isKindOfClass:[BAImageDataEntity class]]) {
        return nil;
    }
    
    BAImageDataEntity *imageEntity = (BAImageDataEntity *)entity;
    
    BAWeak;
    /*! 检查地址中是否有中文 */
    NSString *URLString = [NSURL URLWithString:imageEntity.urlString] ? imageEntity.urlString : [self strUTF8Encoding:imageEntity.urlString];
    
    if (BANetManagerShare.isOpenLog)
    {
        DDLogDebug(@"******************** 请求参数 ***************************");
        DDLogDebug(@"请求头: %@\n请求方式: %@\n请求URL: %@\n请求param: %@\n\n",BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders, @"POST",URLString, imageEntity.parameters);
        DDLogDebug(@"********************************************************");
    }
    if ([CNBaseNetworkConst closeHTTPDNS]) {
        [self ba_setValue:nil forHTTPHeaderKey:@"host"];
    }else{
        // 初始化httpdns实例
        HttpDnsService *httpdns = [HttpDnsService sharedInstance];
        NSURL *aliyunUrl = [NSURL URLWithString:URLString];
        NSString *ip = [httpdns getIpByHostAsync:aliyunUrl.host];
        //    DDLogDebug(@"+++++++阿里云IP:%@",ip);
        [self ba_setValue:aliyunUrl.host forHTTPHeaderKey:@"host"];
        if (ip) {
            // 通过HTTPDNS获取IP成功，进行URL替换和HOST头设置
            //        DDLogDebug(@"+++++++阿里云Get IP(%@) for host(%@) from HTTPDNS Successfully!", ip, aliyunUrl.host);
            NSRange hostFirstRange = [URLString rangeOfString:aliyunUrl.host];
            if (NSNotFound != hostFirstRange.location) {
                NSString *newUrl = [URLString stringByReplacingCharactersInRange:hostFirstRange withString:ip];
                //            DDLogDebug(@"New URL: %@", newUrl);
                //            DDLogDebug(@"+++++++阿里云New URL:%@",newUrl);
                URLString = newUrl;
            }
        }
    }
    
    //    DDLogDebug(@"+++++++阿里云最终URL:%@",URLString);
    
    //阿里云API网关接入参数
    [self signAliyunApiGatewayWithMethod:@"POST" AndPath:[NSURL URLWithString:URLString].path AndParams:imageEntity.parameters];
    
    BAURLSessionTask *sessionTask = nil;
    sessionTask = [BANetManagerShare.sessionManager POST:URLString parameters:imageEntity.parameters headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        @autoreleasepool {
            
            /*! 出于性能考虑,将上传图片进行压缩 */
            [imageEntity.imageArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
                /*! image的压缩方法 */
                UIImage *resizedImage;
                /*! 此处是使用原生系统相册 */
                if ([obj isKindOfClass:[PHAsset class]]) {
                    PHAsset *asset = (PHAsset *)obj;
                    PHCachingImageManager *imageManager = [[PHCachingImageManager alloc] init];
                    [imageManager requestImageForAsset:asset targetSize:CGSizeMake(asset.pixelWidth , asset.pixelHeight) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
                        if (BANetManagerShare.isOpenLog)
                        {
                            DDLogDebug(@" width:%f height:%f",result.size.width,result.size.height);
                        }
                        
                        [self ba_uploadImageWithFormData:formData resizedImage:result imageTypes:imageEntity.imageTypes imageScale:imageEntity.imageScale fileNames:imageEntity.fileNames name:imageEntity.name index:idx];
                    }];
                } else {
                    /*! 此处是使用其他第三方相册，可以自由定制压缩方法 */
                    resizedImage = obj;
                    [self ba_uploadImageWithFormData:formData resizedImage:resizedImage imageTypes:imageEntity.imageTypes imageScale:imageEntity.imageScale fileNames:imageEntity.fileNames name:imageEntity.name index:idx];
                }
            }];
        }
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        if (BANetManagerShare.isOpenLog)
        {
            DDLogDebug(@"上传进度--%lld, 总进度---%lld",uploadProgress.completedUnitCount,uploadProgress.totalUnitCount);
        }
        /*! 回到主线程刷新UI */
        dispatch_async(dispatch_get_main_queue(), ^{
            if (progressBlock) {
                progressBlock(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
            }
        });
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (BANetManagerShare.isOpenLog)
        {
            DDLogDebug(@"上传图片成功 = %@",responseObject);
        }
        if (successBlock) {
            successBlock(responseObject);
        }
        
        [[weakSelf tasks] removeObject:sessionTask];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failureBlock) {
            failureBlock(error);
        }
        [[weakSelf tasks] removeObject:sessionTask];
    }];
    
    if (sessionTask) {
        [[self tasks] addObject:sessionTask];
    }
    
    return sessionTask;
}


/**
 上传图片(多图)
 
 @param entity 请求信息载体
 @param successBlock 上传成功的回调
 @param failureBlock 上传失败的回调
 @param progressBlock 上传进度
 @return BAURLSessionTask
 */
+ (BAURLSessionTask *)ba_uploadImageDataWithEntity:(BADataEntity *)entity
                                      successBlock:(BAResponseSuccessBlock)successBlock
                                       failurBlock:(BAResponseFailBlock)failureBlock
                                     progressBlock:(BAUploadProgressBlock)progressBlock
{
    [BANetManagerShare.sessionManager.requestSerializer setValue:[CNAccountInfoTool csdnIsAudit]?@"1":@"0" forHTTPHeaderField:@"isCsdnAudit"];
    //签名
    NSInteger randomNum = [CSDNTool getRandomNumber:10000 to:100000];
    NSString *currentTimeStamp = [CSDNTool currentTimeStampStr];
    DDLogDebug(@"%@",[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret]);
    NSString *sign = [[[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret] sha1String] uppercaseString];
    [BANetManagerShare.sessionManager.requestSerializer setValue:sign forHTTPHeaderField:@"X-Sign"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:[NSString stringWithFormat:@"%ld",randomNum] forHTTPHeaderField:@"X-RandomNum"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:currentTimeStamp forHTTPHeaderField:@"X-TimeStamp"];
    if (!entity || entity.urlString == nil || ![entity isKindOfClass:[BAImageDataEntity class]]) {
        return nil;
    }
    
    BAImageDataEntity *imageEntity = (BAImageDataEntity *)entity;
    
    BAWeak;
    /*! 检查地址中是否有中文 */
    NSString *URLString = [NSURL URLWithString:imageEntity.urlString] ? imageEntity.urlString : [self strUTF8Encoding:imageEntity.urlString];
    
    if (BANetManagerShare.isOpenLog)
    {
        DDLogDebug(@"******************** 请求参数 ***************************");
        DDLogDebug(@"请求头: %@\n请求方式: %@\n请求URL: %@\n请求param: %@\n\n",BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders, @"POST",URLString, imageEntity.parameters);
        DDLogDebug(@"********************************************************");
    }
    
    
    if ([CNBaseNetworkConst closeHTTPDNS]) {
        [self ba_setValue:nil forHTTPHeaderKey:@"host"];
    }else{
        // 初始化httpdns实例
        HttpDnsService *httpdns = [HttpDnsService sharedInstance];
        NSURL *aliyunUrl = [NSURL URLWithString:URLString];
        NSString *ip = [httpdns getIpByHostAsync:aliyunUrl.host];
        //    DDLogDebug(@"+++++++阿里云IP:%@",ip);
        [self ba_setValue:aliyunUrl.host forHTTPHeaderKey:@"host"];
        if (ip) {
            // 通过HTTPDNS获取IP成功，进行URL替换和HOST头设置
            //        DDLogDebug(@"+++++++阿里云Get IP(%@) for host(%@) from HTTPDNS Successfully!", ip, aliyunUrl.host);
            NSRange hostFirstRange = [URLString rangeOfString:aliyunUrl.host];
            if (NSNotFound != hostFirstRange.location) {
                NSString *newUrl = [URLString stringByReplacingCharactersInRange:hostFirstRange withString:ip];
                //            DDLogDebug(@"New URL: %@", newUrl);
                //            DDLogDebug(@"+++++++阿里云New URL:%@",newUrl);
                URLString = newUrl;
            }
        }
    }
    
    //    DDLogDebug(@"+++++++阿里云最终URL:%@",URLString);
    
    
    //    [formData requestByFinalizingMultipartFormData]
    //    NSString *boundary = AFCreateMultipartFormBoundary();
    //阿里云API网关接入参数
    [self signAliyunApiGatewayWithMethod:@"POST" AndPath:[NSURL URLWithString:URLString].path AndParams:imageEntity.parameters];
    
    BAURLSessionTask *sessionTask = nil;
    sessionTask = [BANetManagerShare.sessionManager POST:URLString parameters:imageEntity.parameters headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        @autoreleasepool {
            /*! 出于性能考虑,将上传图片进行压缩 */
            [imageEntity.imageDataArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                
                /*! image的压缩方法 */
                NSData *resizedImageData;
                resizedImageData = obj;
                [self ba_uploadImageWithFormData:formData resizedImageData:resizedImageData imageTypes:imageEntity.imageTypes imageScale:imageEntity.imageScale fileNames:imageEntity.fileNames name:imageEntity.name index:idx];
                
            }];
        }
        
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        if (BANetManagerShare.isOpenLog)
        {
            DDLogDebug(@"上传进度--%lld, 总进度---%lld",uploadProgress.completedUnitCount,uploadProgress.totalUnitCount);
        }
        /*! 回到主线程刷新UI */
        dispatch_async(dispatch_get_main_queue(), ^{
            if (progressBlock) {
                progressBlock(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
            }
        });
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (BANetManagerShare.isOpenLog)
        {
            DDLogDebug(@"上传图片成功 = %@",responseObject);
        }
        if (successBlock) {
            successBlock(responseObject);
        }
        
        [[weakSelf tasks] removeObject:sessionTask];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failureBlock) {
            failureBlock(error);
        }
        [[weakSelf tasks] removeObject:sessionTask];
    }];
    
    if (sessionTask) {
        [[self tasks] addObject:sessionTask];
    }
    
    return sessionTask;
}

/**
 视频上传
 
 @param entity 请求信息载体
 @param successBlock 成功的回调
 @param failureBlock 失败的回调
 @param progressBlock 上传的进度
 */
+ (void)ba_uploadVideoWithEntity:(BADataEntity *)entity
                    successBlock:(BAResponseSuccessBlock)successBlock
                    failureBlock:(BAResponseFailBlock)failureBlock
                   progressBlock:(BAUploadProgressBlock)progressBlock
{
    if (!entity || entity.urlString == nil || ![entity isKindOfClass:[BAFileDataEntity class]]) {
        return;
    }
    BAFileDataEntity *fileEntity = (BAFileDataEntity *)entity;
    /*! 获得视频资源 */
    AVURLAsset *avAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:fileEntity.filePath]  options:nil];
    
    /*! 压缩 */
    
    //    NSString *const AVAssetExportPreset640x480;
    //    NSString *const AVAssetExportPreset960x540;
    //    NSString *const AVAssetExportPreset1280x720;
    //    NSString *const AVAssetExportPreset1920x1080;
    //    NSString *const AVAssetExportPreset3840x2160;
    
    /*! 创建日期格式化器 */
    
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    
    [formatter setDateFormat:@"yyyy-MM-dd-HH:mm:ss"];
    
    /*! 转化后直接写入Library---caches */
    NSString *videoWritePath = [NSString stringWithFormat:@"output-%@.mp4",[formatter stringFromDate:[NSDate date]]];
    NSString *outfilePath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@", videoWritePath];
    
    AVAssetExportSession *avAssetExport = [[AVAssetExportSession alloc] initWithAsset:avAsset presetName:AVAssetExportPresetMediumQuality];
    
    avAssetExport.outputURL = [NSURL fileURLWithPath:outfilePath];
    avAssetExport.outputFileType =  AVFileTypeMPEG4;
    
    [avAssetExport exportAsynchronouslyWithCompletionHandler:^{
        switch ([avAssetExport status]) {
            case AVAssetExportSessionStatusCompleted:
            {
                [BANetManagerShare.sessionManager POST:fileEntity.urlString parameters:fileEntity.parameters headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
                    
                    NSURL *filePathURL2 = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@", outfilePath]];
                    // 获得沙盒中的视频内容
                    [formData appendPartWithFileURL:filePathURL2 name:@"video" fileName:outfilePath mimeType:@"application/octet-stream" error:nil];
                    
                } progress:^(NSProgress * _Nonnull uploadProgress) {
                    
                    if (BANetManagerShare.isOpenLog)
                    {
                        DDLogDebug(@"上传进度--%lld, 总进度---%lld",uploadProgress.completedUnitCount,uploadProgress.totalUnitCount);
                    }
                    
                    /*! 回到主线程刷新UI */
                    dispatch_async(dispatch_get_main_queue(), ^{
                        if (progressBlock)
                        {
                            progressBlock(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
                        }
                    });
                } success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary *  _Nullable responseObject) {
                    if (BANetManagerShare.isOpenLog)
                    {
                        DDLogDebug(@"上传视频成功 = %@",responseObject);
                    }
                    if (successBlock)
                    {
                        successBlock(responseObject);
                    }
                } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                    if (BANetManagerShare.isOpenLog)
                    {
                        DDLogDebug(@"上传视频失败 = %@", error);
                    }
                    if (failureBlock)
                    {
                        failureBlock(error);
                    }
                }];
                break;
            }
            default:
                break;
        }
    }];
}

/**
 文件下载
 
 @param entity 请求信息载体
 @param successBlock 下载文件成功的回调
 @param failureBlock 下载文件失败的回调
 @param progressBlock 下载文件的进度显示
 @return BAURLSessionTask
 */

+ (BAURLSessionTask *)ba_downLoadFileWithEntity:(BADataEntity *)entity
                                   successBlock:(BAResponseSuccessBlock)successBlock
                                   failureBlock:(BAResponseFailBlock)failureBlock
                                  progressBlock:(BADownloadProgressBlock)progressBlock
{
    if (!entity || entity.urlString == nil || ![entity isKindOfClass:[BAFileDataEntity class]]) {
        return nil;
    }
    
    [BANetManagerShare.sessionManager.requestSerializer setValue:nil forHTTPHeaderField:@"Content-Type"];
    
    BAFileDataEntity *fileEntity = (BAFileDataEntity *)entity;
    
    /*! 检查地址中是否有中文 */
    NSString *URLString = [NSURL URLWithString:fileEntity.urlString] ? fileEntity.urlString : [self strUTF8Encoding:fileEntity.urlString];
    
    if ([CNBaseNetworkConst closeHTTPDNS]) {
        [self ba_setValue:nil forHTTPHeaderKey:@"host"];
    }else{
        // 初始化httpdns实例
        HttpDnsService *httpdns = [HttpDnsService sharedInstance];
        NSURL *aliyunUrl = [NSURL URLWithString:URLString];
        NSString *ip = [httpdns getIpByHostAsync:aliyunUrl.host];
        //    DDLogDebug(@"+++++++阿里云IP:%@",ip);
        [self ba_setValue:aliyunUrl.host forHTTPHeaderKey:@"host"];
        if (ip) {
            // 通过HTTPDNS获取IP成功，进行URL替换和HOST头设置
            //        DDLogDebug(@"+++++++阿里云Get IP(%@) for host(%@) from HTTPDNS Successfully!", ip, aliyunUrl.host);
            NSRange hostFirstRange = [URLString rangeOfString:aliyunUrl.host];
            if (NSNotFound != hostFirstRange.location) {
                NSString *newUrl = [URLString stringByReplacingCharactersInRange:hostFirstRange withString:ip];
                //            DDLogDebug(@"New URL: %@", newUrl);
                //            DDLogDebug(@"+++++++阿里云New URL:%@",newUrl);
                URLString = newUrl;
            }
        }
    }
    
    NSMutableURLRequest *downloadRequest = [BANetManagerShare.sessionManager.requestSerializer requestWithMethod:@"GET" URLString:URLString parameters:entity.parameters error:nil];
    
    if (BANetManagerShare.isOpenLog)
    {
        DDLogDebug(@"******************** 请求参数 ***************************");
        DDLogDebug(@"请求头: %@\n请求方式: %@\n请求URL: %@\n请求param: %@\n\n",BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders, @"download", fileEntity.urlString, fileEntity.parameters);
        DDLogDebug(@"******************************************************");
    }
    
    //阿里云API网关接入参数
    [self signAliyunApiGatewayWithMethod:@"GET" AndPath:[NSURL URLWithString:URLString].path AndParams:fileEntity.parameters];
    BAURLSessionTask *sessionTask = nil;
    
    sessionTask = [BANetManagerShare.sessionManager downloadTaskWithRequest:downloadRequest progress:^(NSProgress * _Nonnull downloadProgress) {
        
        if (BANetManagerShare.isOpenLog)
        {
            DDLogDebug(@"下载进度：%.2lld%%",100 * downloadProgress.completedUnitCount/downloadProgress.totalUnitCount);
        }
        /*! 回到主线程刷新UI */
        dispatch_async(dispatch_get_main_queue(), ^{
            
            if (progressBlock)
            {
                progressBlock(downloadProgress.completedUnitCount, downloadProgress.totalUnitCount);
            }
            
        });
        
    } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
        
        if (!fileEntity.filePath)
        {
            NSURL *downloadURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
            if (BANetManagerShare.isOpenLog)
            {
                DDLogDebug(@"默认路径--%@",downloadURL);
            }
            return [downloadURL URLByAppendingPathComponent:[response suggestedFilename]];
        }
        else
        {
            return [NSURL fileURLWithPath:fileEntity.filePath];
        }
        
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        
        [[self tasks] removeObject:sessionTask];
        if (BANetManagerShare.isOpenLog)
        {
            DDLogDebug(@"下载文件成功");
        }
        if (error == nil)
        {
            if (successBlock)
            {
                /*! 返回完整路径 */
                successBlock([filePath path]);
            }
            else
            {
                if (failureBlock)
                {
                    failureBlock(error);
                }
            }
        }
        else{
            if (failureBlock)
            {
                failureBlock(error);
            }
        }
    }];
    
    /*! 开始启动任务 */
    [sessionTask resume];
    
    if (sessionTask)
    {
        [[self tasks] addObject:sessionTask];
    }
    return sessionTask;
}

/**
 文件上传
 
 @param entity 请求信息载体
 @param successBlock successBlock description
 @param failureBlock failureBlock description
 @param progressBlock progressBlock description
 @return BAURLSessionTask
 */

+ (BAURLSessionTask *)ba_uploadFileWithWithEntity:(BADataEntity *)entity
                                     successBlock:(BAResponseSuccessBlock)successBlock
                                     failureBlock:(BAResponseFailBlock)failureBlock
                                    progressBlock:(BAUploadProgressBlock)progressBlock
{
    if (!entity || entity.urlString == nil || ![entity isKindOfClass:[BAFileDataEntity class]]) {
        return nil;
    }
    
    BAFileDataEntity *fileEntity = (BAFileDataEntity *)entity;
    
    if (BANetManagerShare.isOpenLog)
    {
        DDLogDebug(@"******************** 请求参数 ***************************");
        DDLogDebug(@"请求头: %@\n请求方式: %@\n请求URL: %@\n请求param: %@\n\n",BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders, @"uploadFile", fileEntity.urlString, fileEntity.parameters);
        DDLogDebug(@"******************************************************");
    }
    
    BAURLSessionTask *sessionTask = nil;
    sessionTask = [BANetManagerShare.sessionManager POST:fileEntity.urlString parameters:fileEntity.parameters headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        NSError *error = nil;
        [formData appendPartWithFileURL:[NSURL URLWithString:fileEntity.filePath] name:fileEntity.fileName error:&error];
        if (failureBlock && error)
        {
            failureBlock(error);
        }
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
        if (BANetManagerShare.isOpenLog)
        {
            DDLogDebug(@"上传进度--%lld, 总进度---%lld",uploadProgress.completedUnitCount,uploadProgress.totalUnitCount);
        }
        
        /*! 回到主线程刷新UI */
        dispatch_async(dispatch_get_main_queue(), ^{
            if (progressBlock)
            {
                progressBlock(uploadProgress.completedUnitCount, uploadProgress.totalUnitCount);
            }
        });
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        [[self tasks] removeObject:sessionTask];
        if (successBlock)
        {
            successBlock(responseObject);
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        [[self tasks] removeObject:sessionTask];
        if (failureBlock)
        {
            failureBlock(error);
        }
    }];
    
    /*! 开始启动任务 */
    [sessionTask resume];
    
    if (sessionTask)
    {
        [[self tasks] addObject:sessionTask];
    }
    return sessionTask;
}

#pragma mark - 网络状态监测
/*!
 *  开启网络监测
 */
+ (void)ba_startNetWorkMonitoringWithBlock:(BANetworkStatusBlock)networkStatus
{
    /*! 1.获得网络监控的管理者 */
    AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
    /*! 当使用AF发送网络请求时,只要有网络操作,那么在状态栏(电池条)wifi符号旁边显示  菊花提示 */
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
    /*! 2.设置网络状态改变后的处理 */
    [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        /*! 当网络状态改变了, 就会调用这个block */
        switch (status)
        {
            case AFNetworkReachabilityStatusUnknown:
                DDLogDebug(@"未知网络");
                networkStatus ? networkStatus(BANetworkStatusUnknown) : nil;
                break;
            case AFNetworkReachabilityStatusNotReachable:
                DDLogDebug(@"没有网络");
                networkStatus ? networkStatus(BANetworkStatusNotReachable) : nil;
                break;
            case AFNetworkReachabilityStatusReachableViaWWAN:
                DDLogDebug(@"手机自带网络");
                networkStatus ? networkStatus(BANetworkStatusReachableViaWWAN) : nil;
                break;
            case AFNetworkReachabilityStatusReachableViaWiFi:
                DDLogDebug(@"wifi 网络");
                networkStatus ? networkStatus(BANetworkStatusReachableViaWiFi) : nil;
                break;
        }
    }];
    [manager startMonitoring];
}


/// 停止监控网络状态
+ (void)ba_stopMonitoring{
    AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
    [manager setReachabilityStatusChangeBlock:nil];
    [manager startMonitoring];
}


/*!
 *  是否有网
 *
 *  @return YES, 反之:NO
 */
+ (BOOL)ba_isHaveNetwork
{
    return [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus != AFNetworkReachabilityStatusNotReachable;
}

/*!
 *  是否是手机网络
 *
 *  @return YES, 反之:NO
 */
+ (BOOL)ba_is3GOr4GNetwork
{
    return [AFNetworkReachabilityManager sharedManager].reachableViaWWAN;
}

/*!
 *  是否是 WiFi 网络
 *
 *  @return YES, 反之:NO
 */
+ (BOOL)ba_isWiFiNetwork
{
    return [AFNetworkReachabilityManager sharedManager].reachableViaWiFi;
}


#pragma mark - 取消 Http 请求
/*!
 *  取消所有 Http 请求
 */
+ (void)ba_cancelAllRequest
{
    // 锁操作
    @synchronized(self)
    {
        [[self tasks] enumerateObjectsUsingBlock:^(NSURLSessionTask  *_Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
            [task cancel];
        }];
        [[self tasks] removeAllObjects];
    }
}

/*!
 *  取消指定 URL 的 Http 请求
 */
+ (void)ba_cancelRequestWithURL:(NSString *)URL
{
    if (!URL)
    {
        return;
    }
    @synchronized (self)
    {
        [[self tasks] enumerateObjectsUsingBlock:^(NSURLSessionTask  *_Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
            
            if ([task.currentRequest.URL.absoluteString hasPrefix:URL])
            {
                [task cancel];
                [[self tasks] removeObject:task];
                *stop = YES;
            }
        }];
    }
}


#pragma mark - 压缩图片尺寸
/*! 对图片尺寸进行压缩 */
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
{
    if (newSize.height > 375/newSize.width*newSize.height)
    {
        newSize.height = 375/newSize.width*newSize.height;
    }
    
    if (newSize.width > 375)
    {
        newSize.width = 375;
    }
    
    UIImage *newImage = [UIImage needCenterImage:image size:newSize scale:1.0];
    
    return newImage;
}

#pragma mark - url 中文格式化
+ (NSString *)strUTF8Encoding:(NSString *)str
{
    /*! ios9适配的话 打开第一个 */
    if ([[UIDevice currentDevice] systemVersion].floatValue >= 9.0)
    {
        return [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPathAllowedCharacterSet]];
    }
    else
    {
        return [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    }
}

#pragma mark - setter / getter
/**
 存储着所有的请求task数组
 
 @return 存储着所有的请求task数组
 */
+ (NSMutableArray *)tasks
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        DDLogDebug(@"创建数组");
        tasks = [[NSMutableArray alloc] init];
    });
    return tasks;
}

- (void)setTimeoutInterval:(NSTimeInterval)timeoutInterval
{
    _timeoutInterval = timeoutInterval;
    BANetManagerShare.sessionManager.requestSerializer.timeoutInterval = timeoutInterval;
}

- (void)setRequestSerializer:(BAHttpRequestSerializer)requestSerializer
{
    _requestSerializer = requestSerializer;
    switch (requestSerializer) {
        case BAHttpRequestSerializerJSON:
        {
            BANetManagerShare.sessionManager.requestSerializer = [AFJSONRequestSerializer serializer] ;
        }
            break;
        case BAHttpRequestSerializerHTTP:
        {
            BANetManagerShare.sessionManager.requestSerializer = [AFHTTPRequestSerializer serializer] ;
        }
            break;
            
        default:
            break;
    }
}

- (void)setResponseSerializer:(BAHttpResponseSerializer)responseSerializer
{
    _responseSerializer = responseSerializer;
    switch (responseSerializer) {
        case BAHttpResponseSerializerJSON:
        {
            BANetManagerShare.sessionManager.responseSerializer = [AFJSONResponseSerializer serializer] ;
        }
            break;
        case BAHttpResponseSerializerHTTP:
        {
            BANetManagerShare.sessionManager.responseSerializer = [AFHTTPResponseSerializer serializer] ;
        }
            break;
            
        default:
            break;
    }
}

- (void)setHttpHeaderFieldDictionary:(NSDictionary *)httpHeaderFieldDictionary
{
    _httpHeaderFieldDictionary = httpHeaderFieldDictionary;
    
    if (![httpHeaderFieldDictionary isKindOfClass:[NSDictionary class]])
    {
        DDLogDebug(@"请求头数据有误，请检查！");
        return;
    }
    NSArray *keyArray = httpHeaderFieldDictionary.allKeys;
    
    if (keyArray.count <= 0)
    {
        DDLogDebug(@"请求头数据有误，请检查！");
        return;
    }
    
    for (NSInteger i = 0; i < keyArray.count; i ++)
    {
        NSString *keyString = keyArray[i];
        NSString *valueString = httpHeaderFieldDictionary[keyString];
        
        [BaseNetManager ba_setValue:valueString forHTTPHeaderKey:keyString];
    }
}

/**
 *  自定义请求头
 */
+ (void)ba_setValue:(NSString *)value forHTTPHeaderKey:(NSString *)HTTPHeaderKey
{
    [BANetManagerShare.sessionManager.requestSerializer setValue:value forHTTPHeaderField:HTTPHeaderKey];
}


/**
 删除所有请求头
 */
+ (void)ba_clearAuthorizationHeader
{
    [BANetManagerShare.sessionManager.requestSerializer clearAuthorizationHeader];
}

+ (void)ba_uploadImageWithFormData:(id<AFMultipartFormData>  _Nonnull )formData
                      resizedImage:(UIImage *)resizedImage
                        imageTypes:(NSArray <NSString *> *)imageTypes
                        imageScale:(CGFloat)imageScale
                         fileNames:(NSArray <NSString *> *)fileNames
                              name:(NSString *)name
                             index:(NSUInteger)index
{
    /*! 此处压缩方法是jpeg格式是原图大小的0.8倍，要调整大小的话，就在这里调整就行了还是原图等比压缩 */
    if (imageScale == 0)
    {
        imageScale = 0.8;
    }
    
    //自己添加的压缩
    
    //    float w =  CGRectGetWidth([UIApplication sharedApplication].keyWindow.bounds);
    //    if (resizedImage.size.width > w*0.8)
    //    {
    //        CGFloat fWidth = w*0.8;
    //        CGFloat fHeight = fWidth * resizedImage.size.height / resizedImage.size.width;
    //
    //        CGFloat scale = [[UIScreen mainScreen] scale];
    //        UIGraphicsBeginImageContext(CGSizeMake(fWidth*scale, fHeight*scale));
    //        CGRect frame = CGRectMake(0.0f, 0.0f, fWidth*scale, fHeight*scale);
    //
    //        [resizedImage drawInRect:frame];
    //        resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    //        UIGraphicsEndImageContext();
    //    }
    //
    //    /* Store the message into client info */
    //    float fCompressionRatio = 1.0f;
    //    NSData* imageData = UIImageJPEGRepresentation(resizedImage, fCompressionRatio);
    //
    //    /* AnIM currently support binary data only up to 1 MB
    //     If the image size is more than this size, shrink the data before sending to others */
    //    NSInteger nSizeLimit = 100 * 1024;
    //    while ([imageData length] > nSizeLimit)
    //    {
    //        fCompressionRatio = fCompressionRatio*0.6;
    //        imageData = UIImageJPEGRepresentation(resizedImage, fCompressionRatio);
    //    }
    
    ///
    
    //暂时注释掉
    //NSData *imageData = UIImageJPEGRepresentation(resizedImage, imageScale ?: 1.f);
    NSData *imageData = [[NSData alloc]init];
    if ([imageTypes[index] isEqualToString:@"gif"])
    {
        imageData = [AnimatedGIFImageSerialization animatedGIFDataWithImage:resizedImage error:nil];
        if (imageData.length > 3*1024*1024)
        {
            imageData = [ImageCompress compressImageData:imageData limitDataSize:3*1024*1024];
        }
    }
    else
    {
        imageData = [UIImage imageDataWithOriginalImage:resizedImage quality:imageScale];
    }
    
    /*! 拼接data */
    if (imageData != nil)
    {   // 图片数据不为空才传递 fileName
        //                [formData appendPartWithFileData:imgData name:[NSString stringWithFormat:@"picflie%ld",(long)i] fileName:@"image.png" mimeType:@" image/jpeg"];
        
        // 默认图片的文件名, 若fileNames为nil就使用
        
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = @"yyyyMMddHHmmss";
        NSString *str = [formatter stringFromDate:[NSDate date]];
        NSString *imageFileName = [NSString stringWithFormat:@"%@%ld.%@",str, index, imageTypes[index]?:@"jpg"];
        
        [formData appendPartWithFileData:imageData
                                    name:name ? : [NSString stringWithFormat:@"picflie%ld", index]
                                fileName:fileNames ? [NSString stringWithFormat:@"%@.%@",fileNames[index],imageTypes[index]?:@"jpg"] : imageFileName
                                mimeType:[NSString stringWithFormat:@"image/%@",imageTypes[index] ?: @"jpg"]];
        DDLogDebug(@"上传图片 %lu 成功", (unsigned long)index);
    }
}

+ (void)ba_uploadImageWithFormData:(id<AFMultipartFormData>  _Nonnull )formData
                  resizedImageData:(NSData *)resizedImageData
                        imageTypes:(NSArray <NSString *> *)imageTypes
                        imageScale:(CGFloat)imageScale
                         fileNames:(NSArray <NSString *> *)fileNames
                              name:(NSString *)name
                             index:(NSUInteger)index
{
    /*! 此处压缩方法是jpeg格式是原图大小的0.8倍，要调整大小的话，就在这里调整就行了还是原图等比压缩 */
    if (imageScale == 0)
    {
        imageScale = 0.8;
    }
    
    if ([imageTypes[index] isEqualToString:@"gif"])
    {
        if (resizedImageData.length > 3*1024*1024)
        {
            resizedImageData = [ImageCompress compressImageData:resizedImageData limitDataSize:3*1024*1024];
        }
    }
    else
    {
        resizedImageData = [UIImage imageDataWithOriginalImage:[UIImage imageWithData:resizedImageData] quality:imageScale];
    }
    
    /*! 拼接data */
    if (resizedImageData != nil)
    {   // 图片数据不为空才传递 fileName
        //                [formData appendPartWithFileData:imgData name:[NSString stringWithFormat:@"picflie%ld",(long)i] fileName:@"image.png" mimeType:@" image/jpeg"];
        
        // 默认图片的文件名, 若fileNames为nil就使用
        
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = @"yyyyMMddHHmmss";
        NSString *str = [formatter stringFromDate:[NSDate date]];
        NSString *imageFileName = [NSString stringWithFormat:@"%@%ld.%@",str, index, imageTypes[index]?:@"jpg"];
        
        [formData appendPartWithFileData:resizedImageData
                                    name:name ? : [NSString stringWithFormat:@"picflie%ld", index]
                                fileName:fileNames ? [NSString stringWithFormat:@"%@.%@",fileNames[index],imageTypes[index]?:@"jpg"] : imageFileName
                                mimeType:[NSString stringWithFormat:@"image/%@",imageTypes[index] ?: @"jpg"]];
        DDLogDebug(@"上传图片 %lu 成功", (unsigned long)index);
    }
}

/**
 清空缓存：此方法可能会阻止调用线程，直到文件删除完成。
 */
- (void)ba_clearAllHttpCache
{
    [BaseNetManagerCache ba_clearAllHttpCache];
}

/* URL的结构是 ？ 号之前是地址， ？号之后是参数
 path:http://cache.tuwan.com/app/
 params:@{@"appid":@1, @"class":@"heronews", @"mod":@"八卦", @"appver":@2.1}
 */
//方法：把path和参数拼接起来，把字符串中的中文转换为 百分号 形势，因为有的服务器不接收中文编码
+ (NSString *)percentPathWithPath:(NSString *)path params:(NSDictionary *)params{
    NSMutableString *percentPath =[NSMutableString stringWithString:path];
    NSArray *keys = params.allKeys;
    NSInteger count = keys.count;
    /*  习惯
     for(int i = 0; i < params.allKeys.count; i ++)
     假设for循环循环1000次，params.allKeys实际上调用的[params allKeys], 会调用allKeys1000次。 OC语言特性是runtime，实际上我们调用一个方法，底层操作是有两个列有方法的列表，常用表和总列表。CPU先在常用表中搜索调用的方法指针，如果找不到，再到总列表中搜索。 在总列表中搜索你调用的方法所在的地址，然后调用完毕之后把这个方法名转移到常用方法列表。如果再次执行某个方法就在常用方法列表中搜索调用，效率更高。但是毕竟每次搜索方法都是耗时的，而swift语言则没有运行时，即没有这个搜索过程。 这是swift比oc效率高20%的原因。 为了避免搜索耗时，我们在for循环外部就把调用次数算出来，这样每次for循环只需要去count所在地址读变量值即可。 这样for循环效率更高。
     */
    for (int i = 0; i < count; i++) {
        if (i == 0) {
            [percentPath appendFormat:@"?%@=%@", keys[i], params[keys[i]]];
        }else{
            [percentPath appendFormat:@"&%@=%@", keys[i], params[keys[i]]];
        }
    }
    //把字符串中的中文转为%号形势
    return [percentPath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
}


+ (NSString *)aliGWQueryPathWithPath:(NSString *)path params:(NSDictionary *)params{
    NSMutableString *percentPath =[NSMutableString stringWithString:path];
    
    NSArray *keyArray = params.allKeys;
    NSArray *keys = [keyArray sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    NSInteger count = keys.count;
    for (int i = 0; i < count; i++) {
        if (i == 0) {
            if ([params[keys[i]] isKindOfClass:[NSString class]]) {
                if ([params[keys[i]] isValid]) {
                    [percentPath appendFormat:@"?%@=%@", keys[i], params[keys[i]]];
                }else{
                    [percentPath appendFormat:@"?%@", keys[i]];
                }
            }else{
                [percentPath appendFormat:@"?%@=%@", keys[i], params[keys[i]]];
            }
        }else{
            if ([params[keys[i]] isKindOfClass:[NSString class]]) {
                if ([params[keys[i]] isValid]) {
                    [percentPath appendFormat:@"&%@=%@", keys[i], params[keys[i]]];
                }else{
                    [percentPath appendFormat:@"&%@", keys[i]];
                }
            }else{
                [percentPath appendFormat:@"&%@=%@", keys[i], params[keys[i]]];
            }
            
        }
    }
    //把字符串中的中文转为%号形势
    return percentPath ;
}

+ (BOOL)configureProxies
{
    NSDictionary *proxySettings = CFBridgingRelease(CFNetworkCopySystemProxySettings());
    
    NSArray *proxies = nil;
    
    NSURL *url = [[NSURL alloc] initWithString:@"http://api.m.taobao.com"];
    
    proxies = CFBridgingRelease(CFNetworkCopyProxiesForURL((__bridge CFURLRef)url,
                                                           (__bridge CFDictionaryRef)proxySettings));
    if (proxies.count > 0)
    {
        NSDictionary *settings = [proxies objectAtIndex:0];
        NSString *host = [settings objectForKey:(NSString *)kCFProxyHostNameKey];
        NSString *port = [settings objectForKey:(NSString *)kCFProxyPortNumberKey];
        
        if (host || port)
        {
            return YES;
        }
    }
    return NO;
}

+(void)signAliyunApiGatewayWithMethod:(NSString *)method AndPath:(NSString *)path AndParams:(NSDictionary *)params
{
    //阿里API网关签名
    [BANetManagerShare.sessionManager.requestSerializer setValue:GATEWAY_APPKEY forHTTPHeaderField:@"X-Ca-Key"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:[CSDNTool currentTimeStampStr] forHTTPHeaderField:@"X-Ca-Timestamp"];
    NSString *signature = [self buildStringToSignWithMethod:method AndPath:path AndParams:params];
    signature = [CAUtils hmacSHA256: signature withSecret:GATEWAY_APPSECRET];
    [BANetManagerShare.sessionManager.requestSerializer setValue:signature forHTTPHeaderField:@"X-Ca-Signature"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:@"X-Ca-Timestamp,X-Ca-Key" forHTTPHeaderField:@"X-Ca-Signature-Headers"];
    if (![[CNChangeHostManager sharedChangeHostObject].kXCaStage isEqualToString:@"RELEASE"]) {
        [BANetManagerShare.sessionManager.requestSerializer setValue:[CNChangeHostManager sharedChangeHostObject].kXCaStage forHTTPHeaderField:@"X-Ca-Stage"];
    }else{
        [BANetManagerShare.sessionManager.requestSerializer setValue:nil forHTTPHeaderField:@"X-Ca-Stage"];
    }
}

/**
 String stringToSign=
 HTTPMethod + "\n" +
 Accept + "\n"
 Content-MD5 + "\n"
 Content-Type + "\n" +
 Date + "\n" +
 Headers +
 Url
 
 POST
 application/json; charset=utf-8
 
 application/x-www-form-urlencoded; charset=utf-8
 Fri, 11 May 2018 03:52:28 GMT+00:00
 x-ca-key:23524193
 x-ca-nonce:bb195952-b62f-4ad6-8b5a-893089c489f8
 x-ca-seq:0
 x-ca-timestamp:1526010748924
 x-ca-websocket_api_type:REGISTER
 /register?Password=test&Username=test&password=test&username=test
 */

+ (NSString *)buildStringToSignWithMethod:(NSString *)method AndPath:(NSString *)path AndParams:(NSDictionary *)params
{
    NSMutableString *s = [[NSMutableString alloc]init];
    // HTTPMethod + "\n"
    [s appendString: method];
    [s appendString: CLOUDAPI_LF];
    // Accept + "\n"
    if ([BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders objectForKey:@"Accept"]) {
        [s appendString: [BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders objectForKey:@"Accept"]];
    }
    
    [s appendString: CLOUDAPI_LF];
    // Content-MD5 + "\n"
    if ([BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders objectForKey:@"Content-MD5"]) {
        [s appendString: [BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders objectForKey:@"Content-MD5"]];
    }
    [s appendString: CLOUDAPI_LF];
    // ContentType: "\n"
    if ([BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders objectForKey:@"X-Ca-Signed-Content-Type"]) {
        [s appendString: [BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders objectForKey:@"X-Ca-Signed-Content-Type"]];
    }
    [s appendString: CLOUDAPI_LF];
    // Date + "\n"
    if ([BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders objectForKey:@"Date"]) {
        [s appendString: [BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders objectForKey:@"Date"]];
    }
    [s appendString: CLOUDAPI_LF];
    
    [s appendString:[self buildHeaders:BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders]];
    if ([method isEqualToString:@"GET"]) {
        // Url and Params
        [s appendString: [self aliGWQueryPathWithPath:path params:params]];
    }else{
        [s appendString:path];
    }
    return s;
}

/**
 * 将headers合成一个字符串
 * 需要注意的是，HTTP头需要按照字母排序加入签名字符串
 * 同时所有加入签名的头的列表，需要用逗号分隔形成一个字符串，加入一个新HTTP头@"X-Ca-Signature-Headers"
 */
+(NSString *)buildHeaders:(NSDictionary *)headers
{
    
    NSArray *keyArray = [headers allKeys];
    NSArray *sortArray = [keyArray sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2 options:NSNumericSearch];
    }];
    
    NSMutableString *mutableStr = [[NSMutableString alloc]init];
    for (NSString *key in sortArray) {
        if ([key hasPrefix:@"X-Ca-Key"] || [key hasPrefix:@"X-Ca-Timestamp"]) {
            [mutableStr appendString:key];
            [mutableStr appendString:@":"];
            [mutableStr appendString:[headers objectForKey:key]];
            [mutableStr appendString:CLOUDAPI_LF];
        }
    }
    return [mutableStr copy];
}

// 获取header
+ (NSDictionary *)getSighHeaderWithMethod:(NSString *)method AndPath:(NSString *)path AndParams:(NSDictionary *)params{
    NSString *URLString = [NSURL URLWithString:path] ? path : [self strUTF8Encoding:path];
    
    [BANetManagerShare.sessionManager.requestSerializer setValue:[CNAccountInfoTool csdnIsAudit]?@"1":@"0" forHTTPHeaderField:@"isCsdnAudit"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@",(([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditToken]:CN_GWTToken)] forHTTPHeaderField:@"Authorization"];
    if ((([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin]) && [CNAccountInfoTool auditToken] != nil) || [[NSUserDefaults standardUserDefaults]objectForKey:kCSDNToken]!= nil)
    {
        //配置Token
        [BANetManagerShare.sessionManager.requestSerializer setValue:(([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditToken]:CN_GWTToken) forHTTPHeaderField:@"JWT-TOKEN"];
    }else
    {
        [BANetManagerShare.sessionManager.requestSerializer setValue:nil forHTTPHeaderField:@"JWT-TOKEN"];
    }
    
    [BANetManagerShare.sessionManager.requestSerializer setValue:(([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditUserToken]:[CNAccountInfoTool userToken]) forHTTPHeaderField:@"UserToken"];
    //签名
    NSInteger randomNum = [CSDNTool getRandomNumber:10000 to:100000];
    NSString *currentTimeStamp = [CSDNTool currentTimeStampStr];
    DDLogDebug(@"%@",[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret]);
    NSString *sign = [[[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret] sha1String] uppercaseString];
    [BANetManagerShare.sessionManager.requestSerializer setValue:sign forHTTPHeaderField:@"X-Sign"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:[NSString stringWithFormat:@"%ld",randomNum] forHTTPHeaderField:@"X-RandomNum"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:currentTimeStamp forHTTPHeaderField:@"X-TimeStamp"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [BANetManagerShare.sessionManager.requestSerializer setValue:nil forHTTPHeaderField:@"host"];
    //阿里云API网关接入参数
    //    [self signAliyunApiGatewayWithMethod:[method uppercaseString] AndPath:[NSURL URLWithString:URLString].path AndParams:params];
    
    return BANetManagerShare.sessionManager.requestSerializer.HTTPRequestHeaders;
    
    //    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    //    dict[@"X-Accept-Language"] = @"zh-cn";
    //    dict[@"platform"] = @"ios";
    //    dict[@"version"] = kAPPVersion;
    //    dict[@"X-Device-ID"] = CN_UUID;
    //    dict[@"X-App-ID"] = @"CSDN-APP";
    //    dict[@"X-OS"] = @"iOS";
    //    dict[@"X-Access-Token"] = [CNAccountInfoTool getCSDNAccessToken];
    //    dict[@"Accept"] = @"application/json";
    //    dict[@"X-Ca-Signed-Content-Type"] = @"application/json";
    //
    //    char deviceToken[384] = {0};
    //    int re =[YunCeng GetSession:deviceToken :384];
    //    NSString * astring = [NSString stringWithUTF8String:deviceToken];
    //    dict[@"DeviceToken"] = astring;
    //
    //
    //    dict[@"isCsdnAudit"] = [CNAccountInfoTool csdnIsAudit]?@"1":@"0";
    //    dict[@"Authorization"] = [NSString stringWithFormat:@"Bearer %@",(([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditToken]:CN_GWTToken)];
    //    if ((([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin]) && [CNAccountInfoTool auditToken] != nil) || [[NSUserDefaults standardUserDefaults]objectForKey:kCSDNToken]!= nil)
    //    {
    //        dict[@"JWT-TOKEN"] = (([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditToken]:CN_GWTToken);
    //
    //    }
    //    dict[@"UserToken"] = (([CNAccountInfoTool csdnIsAudit] && ![CNAccountInfoTool isLogin])?[CNAccountInfoTool auditUserToken]:[CNAccountInfoTool userToken]);
    //
    //    NSInteger randomNum = [CSDNTool getRandomNumber:10000 to:100000];
    //    NSString *currentTimeStamp = [CSDNTool currentTimeStampStr];
    //    NSString *sign = [[[NSString stringWithFormat:@"%@%ld%@%@",CN_UUID,randomNum,currentTimeStamp,CNAPPSecret] sha1String] uppercaseString];
    //     dict[@"X-Sign"] = sign;
    //    dict[@"X-RandomNum"] = [NSString stringWithFormat:@"%ld",randomNum];
    //    dict[@"X-TimeStamp"] = currentTimeStamp;
    //
    //    dict[@"utm_source"] = [CNAccountInfoTool getUtmSource]?:@"";
    //    dict[@"Content-Type"] = @"application/json";
    //
    //
    //    //阿里API网关签名
    //    dict[@"X-Ca-Key"] = GATEWAY_APPKEY;
    //    dict[@"X-Ca-Timestamp"] = [CSDNTool currentTimeStampStr];
    //
    //    NSString *signature = [self buildStringToSignWithMethod:method AndPath:path AndParams:params];
    //    signature = [CAUtils hmacSHA256: signature withSecret:GATEWAY_APPSECRET];
    //    dict[@"X-Ca-Signature"] = signature;
    //    dict[@"X-Ca-Signature-Headers"] = @"X-Ca-Timestamp,X-Ca-Key";
    //    if (![kXCaStage isEqualToString:@"RELEASE"]) {
    //        dict[@"X-Ca-Stage"] = kXCaStage;
    //    }
    //    return [NSDictionary dictionaryWithDictionary:dict];
}
/// 获取当前网络z状态
+ (NSString *)currentNetwork{
    AFNetworkReachabilityStatus status = [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus;
    switch (status) {
        case AFNetworkReachabilityStatusUnknown:
            return @"Unknown";
            break;
        case AFNetworkReachabilityStatusNotReachable:
            return @"NotReachable";
            break;
        case AFNetworkReachabilityStatusReachableViaWWAN:
            return @"WWAN";
            break;
        case AFNetworkReachabilityStatusReachableViaWiFi:
            return @"WiFi";
            break;
        default:
            break;
    }
    return @"UNKNOWN";
}

@end

#pragma mark - NSDictionary,NSArray的分类
/*
 ************************************************************************************
 *新建 NSDictionary 与 NSArray 的分类, 控制台打印 json 数据中的中文
 ************************************************************************************
 */

#ifdef DEBUG
@implementation NSArray (BaseNetManager)

- (NSString *)descriptionWithLocale:(id)locale
{
    NSMutableString *strM = [NSMutableString stringWithString:@"(\n"];
    
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [strM appendFormat:@"\t%@,\n", obj];
    }];
    
    [strM appendString:@")"];
    
    return strM;
}

@end

@implementation NSDictionary (BaseNetManager)

- (NSString *)descriptionWithLocale:(id)locale
{
    NSMutableString *strM = [NSMutableString stringWithString:@"{\n"];
    
    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        [strM appendFormat:@"\t%@ = %@;\n", key, obj];
    }];
    
    [strM appendString:@"}\n"];
    
    return strM;
}


@end

#endif
